package com.ruoyix.im.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyix.common.core.domain.PageQuery;
import com.ruoyix.common.core.domain.R;
import com.ruoyix.common.core.domain.entity.SysUser;
import com.ruoyix.common.core.page.TableDataInfo;
import com.ruoyix.common.helper.LoginHelper;
import com.ruoyix.common.utils.StringUtils;

import com.ruoyix.im.domain.ImChatUserFriend;
import com.ruoyix.im.domain.ImChatUserMessage;
import com.ruoyix.im.domain.bo.ImChatUserMessageBo;
import com.ruoyix.im.domain.vo.ImChatUserMessageVo;
import com.ruoyix.im.domain.vo.UserMessageVO;
import com.ruoyix.im.mapper.ImChatUserFriendMapper;
import com.ruoyix.im.mapper.ImChatUserMessageMapper;
import com.ruoyix.im.service.IImChatUserMessageService;
import com.ruoyix.im.websocket.ImConfigConst;
import com.ruoyix.system.mapper.SysUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 单聊记录Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-27
 */
@RequiredArgsConstructor
@Service
public class ImChatUserMessageServiceImpl extends ServiceImpl<ImChatUserMessageMapper, ImChatUserMessage> implements IImChatUserMessageService {

    private final ImChatUserMessageMapper baseMapper;
    private final SysUserMapper sysUserMapper;
    private  final ImChatUserFriendMapper imChatUserFriendMapper;
    /**
     * 查询单聊记录
     */
    @Override
    public ImChatUserMessageVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询单聊记录列表
     */
    @Override
    public TableDataInfo<ImChatUserMessageVo> queryPageList(ImChatUserMessageBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ImChatUserMessage> lqw = buildQueryWrapper(bo);
        Page<ImChatUserMessageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询单聊记录列表
     */
    @Override
    public List<ImChatUserMessageVo> queryList(ImChatUserMessageBo bo) {
        LambdaQueryWrapper<ImChatUserMessage> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ImChatUserMessage> buildQueryWrapper(ImChatUserMessageBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ImChatUserMessage> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getFromId() != null, ImChatUserMessage::getFromId, bo.getFromId());
        lqw.eq(bo.getToId() != null, ImChatUserMessage::getToId, bo.getToId());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), ImChatUserMessage::getContent, bo.getContent());
        lqw.eq(bo.getMessageStatus() != null, ImChatUserMessage::getMessageStatus, bo.getMessageStatus());
        return lqw;
    }

    /**
     * 新增单聊记录
     */
    @Override
    public Boolean insertByBo(ImChatUserMessageBo bo) {
        ImChatUserMessage add = BeanUtil.toBean(bo, ImChatUserMessage.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改单聊记录
     */
    @Override
    public Boolean updateByBo(ImChatUserMessageBo bo) {
        ImChatUserMessage update = BeanUtil.toBean(bo, ImChatUserMessage.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ImChatUserMessage entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除单聊记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    @Override
    public R<Page> listSystemMessage(Long current, Long size) {
        Page<ImChatUserMessage> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);

        LambdaQueryChainWrapper<ImChatUserMessage> lambdaQuery = lambdaQuery();
        lambdaQuery.select(ImChatUserMessage::getId, ImChatUserMessage::getContent, ImChatUserMessage::getCreateTime);

        lambdaQuery.eq(ImChatUserMessage::getFromId, ImConfigConst.DEFAULT_SYSTEM_MESSAGE_ID);
        lambdaQuery.eq(ImChatUserMessage::getToId, ImConfigConst.DEFAULT_SYSTEM_MESSAGE_ID);
        lambdaQuery.orderByDesc(ImChatUserMessage::getCreateTime);
        Page<ImChatUserMessage> result = lambdaQuery.page(page);
        List<ImChatUserMessage> records = result.getRecords();
        Collections.reverse(records);
        if (CollectionUtils.isEmpty(records)) {
            return R.ok(result);
        } else {
            List<UserMessageVO> collect = records.stream().map(message -> {
                UserMessageVO userMessageVO = new UserMessageVO();
                userMessageVO.setContent(message.getContent());
                userMessageVO.setId(message.getId());
                userMessageVO.setCreateTime(message.getCreateTime());
                return userMessageVO;
            }).collect(Collectors.toList());
            Page<UserMessageVO> resultVO = new Page<>();
            resultVO.setRecords(collect);
            resultVO.setTotal(result.getTotal());
            resultVO.setCurrent(result.getCurrent());
            resultVO.setSize(result.getSize());
            return R.ok(resultVO);
        }
    }


    @Override
    public void saveSystemMessage(String content) {
        ImChatUserMessage userMessage = new ImChatUserMessage();
        userMessage.setContent(content);
        userMessage.setFromId(ImConfigConst.DEFAULT_SYSTEM_MESSAGE_ID);
        userMessage.setToId(ImConfigConst.DEFAULT_SYSTEM_MESSAGE_ID);
        userMessage.setMessageStatus(1);
        save(userMessage);
    }


    public R<Page> listFriendMessage(Long current, Long size, Long friendId) {
        Page<ImChatUserMessage> page = new Page<>();
        page.setCurrent(current);
        page.setSize(size);

        Long userId = LoginHelper.getUserId();

        LambdaQueryChainWrapper<ImChatUserMessage> lambdaQuery = lambdaQuery();
        lambdaQuery.and(wrapper -> wrapper.eq(ImChatUserMessage::getFromId, userId).eq(ImChatUserMessage::getToId, friendId))
            .or(wrapper -> wrapper.eq(ImChatUserMessage::getFromId, friendId).eq(ImChatUserMessage::getToId, userId));
        lambdaQuery.orderByDesc(ImChatUserMessage::getCreateTime);
        Page<ImChatUserMessage> result = lambdaQuery.page(page);
        List<ImChatUserMessage> records = result.getRecords();
        Collections.reverse(records);
        if (CollectionUtils.isEmpty(records)) {
            return R.ok(result);
        } else {
            List<UserMessageVO> collect = records.stream().map(message -> {
                UserMessageVO userMessageVO = new UserMessageVO();
                userMessageVO.setContent(message.getContent());
                userMessageVO.setFromId(message.getFromId());
                userMessageVO.setToId(message.getToId());
                userMessageVO.setMessageStatus(message.getMessageStatus());
                userMessageVO.setId(message.getId());
                userMessageVO.setCreateTime(message.getCreateTime());
                SysUser from = sysUserMapper.selectUserById(message.getFromId());
                if (from != null) {
                    userMessageVO.setAvatar(from.getAvatar());
                }
                return userMessageVO;
            }).collect(Collectors.toList());
            Page<UserMessageVO> resultVO = new Page<>();
            resultVO.setRecords(collect);
            resultVO.setTotal(result.getTotal());
            resultVO.setCurrent(result.getCurrent());
            resultVO.setSize(result.getSize());
            return R.ok(resultVO);
        }
    }


    @Override
    public Map<Long, List<ImChatUserMessageVo>> getChatUserMessageListByUserId(Long userId){
        LambdaQueryWrapper<ImChatUserMessage> lqw = Wrappers.lambdaQuery();
        lqw.eq(ImChatUserMessage::getFromId, userId).or().eq( ImChatUserMessage::getToId, userId).orderByAsc(ImChatUserMessage::getCreateTime);

        LambdaQueryWrapper<ImChatUserFriend> uu = Wrappers.lambdaQuery();
        uu.eq(ImChatUserFriend::getUserId,userId);
        uu.eq(ImChatUserFriend::getFriendStatus,1L);
        List<Long> haveFrends = imChatUserFriendMapper.selectList(uu).stream().map(ImChatUserFriend::getFriendId).collect(Collectors.toList());


        List<ImChatUserMessageVo> imChatUserMessageVos = baseMapper.selectVoList(lqw);
        List<Long> friends = new ArrayList<>();
        imChatUserMessageVos.forEach(item->{
            if(!friends.contains(item.getFromId())&& !Objects.equals(item.getFromId(), userId) && haveFrends.contains(item.getFromId())){
                friends.add(item.getFromId());
            }
            if(!friends.contains(item.getToId())&& !Objects.equals(item.getToId(), userId)&& haveFrends.contains(item.getToId())){
                friends.add(item.getToId());
            }
        });


        Map<Long,List<ImChatUserMessageVo>> result = new HashMap<>();
        friends.forEach(item->{
            List<ImChatUserMessageVo> collect = imChatUserMessageVos.stream().filter(x -> Objects.equals(x.getFromId(), item) || Objects.equals(x.getToId(), item)).sorted(Comparator.comparing(ImChatUserMessageVo::getCreateTime)).collect(Collectors.toList());
            result.put(item,collect);
        });

        return result;
    }


    @Override
    public void setMessageRead(Long fromId,Long toId){
        UpdateWrapper<ImChatUserMessage> wrapper=new UpdateWrapper<>();
        wrapper.set("message_status","1").eq("from_id",fromId).eq("to_id",toId);//更新的条件
        baseMapper.update(wrapper);
    }
}
